/*
 * @Author: your name
 * @Date: 2020-12-17 10:31:19
 * @LastEditTime: 2020-12-17 15:24:00
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \react-typescript-build-env\webpack.config.js
 */
/* 用于自动生成html,并默认将打包生成的js、css引入到html文件中，其中minify 配置项有很多，具体可以参照html-minifier */
const HtmlWebpackPlugin = require("html-webpack-plugin");
/* 将css独立拆包最大的好处就是js和css的改动，不会影响对方。比如我改了js文件并不会导致css文件的缓存失效。 */
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
/* 在webpack打包时优化压缩css代码，主要使用 cssnano 压缩器，这个就不是配置在 plugins 里了，而是 optimization 下的 minimizer。 */
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
/* 用于清除本地文件，在进行生产环境打包的时候，如果不清除dist文件夹，那么每次打包都会生成不同的js文件或者css文件堆积在文件夹中，注意版本带来的使用不同。 */
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
/* 而它用来压缩 js 代码，之前用到的是 uglifyjs-webpack-plugin 这一个，但是它好像需要 babel 的支持，而且现在官方推荐用 terser-webpack-plugin， 不过在使用上差不多，而且它不需要安装 */
const TerserPlugin = require("terser-webpack-plugin");
/* 打包生成的 runtime.js非常的小，gzip 之后一般只有几 kb，但这个文件又经常会改变，我们每次都需要重新请求它，它的 http 耗时远大于它的执行时间了，所以建议不要将它单独拆包，有关优化就是将他将它内联到我们的 index.html 之中。 */
const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin");
/* 如果你想看你webpack打包之后输出文件的大小占比，可以使用这个插件，在webpack.prod.js 中加入如下配置，如果你想控制这个插件是否引入，可以使用一个变量： */
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;
const autoprefixer = require("autoprefixer");
const path = require("path");
/* 打包路径 */
const buildPath = "dist";
/* 环境 dev prod */
const APP_ENV = process.env.NODE_ENV;

const WebpackConfig = {
  entry: path.resolve(__dirname, "src/index.tsx"),
  output: {
    path: path.resolve(__dirname, buildPath),
    filename: "js/[name].[chunkhash].js",
    // publicPath:"/js"
  },
  cache: true,
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        include: [path.resolve("./src")],
        use: [
          {
            loader: "babel-loader",
          },
        ],
        // 排除node_modules底下的
        exclude: /node_modules/,
      },
      {
        test: /\.(c|sc|sa)ss$/,
        use: [
          APP_ENV !== "development"
            ? MiniCssExtractPlugin.loader
            : "style-loader",

          "css-loader",
          "postcss-loader",
          {
            loader: "sass-loader",
            options: {
              implementation: require("dart-sass"),
            },
          },
        ],
      },
      {
        test: /\.(png|jpg|gif|woff|svg|ttf)$/,
        use: ["file-loader"],
      },
    ],
  },
  plugins: [
    /* 动态html */
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "public/index.html"),
      title: "ts-react-starter",
      filename: "index.html",
    }),
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "css/[name].[contenthash].css",
      chunkFilename: "css/[name].[id].[contenthash].css",
    }),
    /* 在webpack打包时优化压缩css代码，主要使用 cssnano 压缩器，这个就不是配置在 plugins 里了，而是 optimization 下的 minimizer。 */
    new CleanWebpackPlugin(),
    // 注意一定要在HtmlWebpackPlugin之后引用
    // inline 的name 和你 runtimeChunk 的 name保持一致
    new ScriptExtHtmlWebpackPlugin({
      //`runtime` must same as runtimeChunk name. default is `runtime`
      inline: /runtime\..*\.js$/,
    }),
  ],
  resolve: {
    extensions: [".ts", ".tsx", ".js", ".jsx"],
    modules: ["src", "node_modules"],
    alias: { "@": path.resolve(__dirname, "src") },
  },

  optimization: {
    // 性能配置
    // ...
    minimizer: [
      /* 在webpack打包时优化压缩css代码，主要使用 cssnano */
      new OptimizeCSSAssetsPlugin({
        cssProcessor: require("cssnano"), // 使用 cssnano 压缩器
        cssProcessorOptions: {
          reduceIdents: false,
          autoprefixer: false,
          safe: true,
          discardComments: {
            removeAll: true,
          },
        },
      }),
    ],
    runtimeChunk: true,
    splitChunks: {
      chunks: "async", // 提取的 chunk 类型，all: 所有，async: 异步，initial: 初始
      // minSize: 30000, // 默认值，新 chunk 产生的最小限制 整数类型（以字节为单位）
      // maxSize: 0, // 默认值，新 chunk 产生的最大限制，0为无限 整数类型（以字节为单位）
      // minChunks: 1, // 默认值，新 chunk 被引用的最少次数
      // maxAsyncRequests: 5, // 默认值，按需加载的 chunk，最大数量
      // maxInitialRequests: 3, // 默认值，初始加载的 chunk，最大数量
      // name: true, // 默认值，控制 chunk 的命名
      cacheGroups: {
        // 配置缓存组
        vendor: {
          name: "vendor",
          chunks: "initial",
          priority: 10, // 优先级
          reuseExistingChunk: false, // 允许复用已经存在的代码块
          test: /node_modules\/(.*)\.js/, // 只打包初始时依赖的第三方
        },
        common: {
          name: "common",
          chunks: "initial",
          // test: resolve("src/components"), // 可自定义拓展你的规则
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true,
        },
      },
    },
  },
  // performance: {
  //   // 性能提示，可以提示过大文件
  //   hints: false, // 性能提示开关 false | "error" | "warning"
  //   maxAssetSize: 100000, // 生成的文件最大限制 整数类型（以字节为单位）
  //   maxEntrypointSize: 100000, // 引入的文件最大限制 整数类型（以字节为单位）
  //   assetFilter: function (assetFilename) {
  //     // 提供资源文件名的断言函数
  //     return /\.(png|jpe?g|gif|svg)(\?.*)?$/.test(assetFilename);
  //   },
  // },
  devServer: {
    contentBase: path.resolve(__dirname, buildPath),
    compress: true,
    port: 3000,
    open: true,
    overlay: true,
    clientLogLevel: "silent",
    quiet: false,
    hot: true,
    https: true,
    historyApiFallback: {
      rewrite: { from: /^\/$/, to: 'index.html' },
    },

  },
};

if (APP_ENV === "production") {
  WebpackConfig.plugins.push(
    new BundleAnalyzerPlugin() /* 而它用来压缩 js 代码，之前用到的是 uglifyjs-webpack-plugin 这一个，但是它好像需要 babel 的支持，而且现在官方推荐用 terser-webpack-plugin， 不过在使用上差不多，而且它不需要安装。 */,
    new TerserPlugin({
      // parallel: true,
      terserOptions: {
        compress: {
          warnings: true,
          drop_console: true,
          drop_debugger: true,
          pure_funcs: ["console.log"], // 移除console
        },
      },
    })
  );
}

module.exports = WebpackConfig;
